package com.njuse.seecjvm.instructions.invoke;

import com.njuse.seecjvm.instructions.base.Index16Instruction;
import com.njuse.seecjvm.memory.jclass.InitState;
import com.njuse.seecjvm.memory.jclass.JClass;
import com.njuse.seecjvm.memory.jclass.Method;
import com.njuse.seecjvm.memory.jclass.runtimeConstantPool.constant.Constant;
import com.njuse.seecjvm.memory.jclass.runtimeConstantPool.constant.ref.InterfaceMethodRef;
import com.njuse.seecjvm.memory.jclass.runtimeConstantPool.constant.ref.MethodRef;
import com.njuse.seecjvm.runtime.StackFrame;
import com.njuse.seecjvm.runtime.Vars;
import com.njuse.seecjvm.runtime.struct.JObject;
import com.njuse.seecjvm.runtime.struct.Slot;

import java.nio.ByteBuffer;


public class INVOKE_INTERFACE extends Index16Instruction {

    /**
     * TODO：实现这个方法
     * 这个方法用于读取这条指令操作码以外的部分
     */
    @Override
    public void fetchOperands(ByteBuffer reader) {
      this.index = (int) reader.getShort() & 0xFFFF;
      short x =reader.getShort();
    }

    /**
     * TODO：实现这条指令
     */
    @Override
    public void execute(StackFrame frame) {
    	
      InterfaceMethodRef t=(InterfaceMethodRef)frame.getMethod().getClazz().getRuntimeConstantPool().getConstant(index);
      Method method=t.resolveInterfaceMethodRef();
      
      
      int argc = method.getArgc();
      
      assert t instanceof InterfaceMethodRef;
      Slot[] argv = new Slot[argc];
      for (int i = 0; i < argc; i++) {
          argv[i] = frame.getOperandStack().popSlot();
      }

      JObject thisRef = frame.getOperandStack().popObjectRef();
      Method invoke=t.resolveInterfaceMethodRef(thisRef.getClazz());
      if (invoke==method) {System.out.println("yes");
  	System.out.println("method:"+method.getClazz().getName());}
      else {
      	System.out.println("no");
    	System.out.println("method:"+method.getClazz().getName());
    	System.out.println("invoke:"+invoke.getClazz().getName());
      }
      StackFrame newFrame = new StackFrame(frame.getThread(), invoke,
              invoke.getMaxStack(), invoke.getMaxLocal() + 1);      //为什么+1
      Vars localVars = newFrame.getLocalVars();
      Slot slot = new Slot();
      slot.setObject(thisRef);
      localVars.setSlot(0, slot);//为什么要把这个对象放进0号槽？
      for (int i = 1; i < argv.length + 1; i++) {
          localVars.setSlot(i, argv[argc - i]);
      }

      frame.getThread().pushFrame(newFrame);
      
    	
    	
    }

  
}
